use actix_web::{delete, get, post, put, web, Responder, ResponseError, HttpRequest};
use crate::data::ShareData;
use crate::models::user::{User, NewUser, ResUserInfo};
use crate::api::{Res, Data, BusinessError};
use crate::models::CRUD;
use crate::models::user::form::{NewUserForm, NewTokenForm};
use log::Level;
use crate::srv::user::login;
use regex::Regex;
use crate::utils::check_permission;
use crate::db_type::Role;
use chrono::NaiveDateTime;
use crate::models::user_info::{UserInfo, NewUserInfo};
use diesel::result::Error::DatabaseError;
use diesel::result::DatabaseErrorKind::UniqueViolation;

#[post("/users")]
pub async fn create_user(
    req: HttpRequest,
    user: web::Json<NewUserForm>,
    data: web::Data<ShareData>,
) -> Res {

    // 至少需要老师权限，才能创建用户
    let ret = check_permission(&req, Role::Teacher);
    if let Err(err) = ret {
        return err.into();
    }

    let claims = ret.unwrap();

    let new_user_form = user.into_inner();
    let mut user_data: NewUser = new_user_form.clone().into();
    user_data.sid = claims.school_id;

    if let Some(r) = user_data.role.clone() {
        // 如果当前账号权限小于等于要创建的账号权限，那么就提示没有权限
        if claims.role.order() < Role::from(r).order() {
            return BusinessError::Forbidden.into();
        }
    } else { // 如果为 None 就表示创建游客账号，提示不能创建游客账号
        return BusinessError::ValidationError { msg: "不能创建游客账号".to_string() }.into();
    }


    // 校验用户信息
    let len = user_data.username.clone().chars().count();
    println!("username length:{}", len);
    if len == 0 {
        return BusinessError::ValidationError { msg: "用户名不能为空。".to_string() }.into();
    } else if len > 6 {
        return BusinessError::ValidationError { msg: "用户名最长为 6 个字".to_string() }.into();
    }

    // 手机号格式校验
    if user_data.phone.clone().len() == 0 {
        return BusinessError::ValidationError { msg: "手机号不能为空。".to_string() }.into();
    }
    let re = Regex::new(r"^[1]([3-9])[0-9]{9}$").expect("手机号正则错误");
    if !re.is_match(user_data.phone.clone().as_str()) {
        return BusinessError::ValidationError { msg: "手机号格式不正确".to_string() }.into();
    }

    // 密码格式校验
    let len = user_data.password.clone().len();
    if len == 0 {
        return BusinessError::ValidationError { msg: "密码不能为空。".to_string() }.into();
    } else if len < 6 || len > 100 {
        return BusinessError::ValidationError { msg: "密码长度必须大于 6 个字符".to_string() }.into();
    }


    let conn = data.postgres();
    match User::create(&conn, &user_data) {
        Ok(u) => {
            // 添加用户信息
            let mut new_user_info = NewUserInfo::from(new_user_form);
            new_user_info.uid = u.id;
            UserInfo::create(&conn, &new_user_info).expect("xxx");

            return if let Some(res_user_info) = ResUserInfo::get_by_uid(&conn, u.id) {
                Data::ok(res_user_info).to_json()
            } else {
                BusinessError::NotFound.into()
            };
        }
        Err(e) => {
            if let DatabaseError(e, msg) = e {
                if let UniqueViolation = e {
                    return BusinessError::ValidationError { msg: "该用户已存在，请检查手机号是否正确！".to_string() }.into();
                }
            }
            return BusinessError::ValidationError { msg: "添加用户出错".to_string() }.into();
        }
    }
}


#[get("/users")]
pub async fn get_user_info(
    data: web::Data<ShareData>,
    req: HttpRequest,
) -> Res {
    let ret = check_permission(&req, Role::Student);

    let conn = data.postgres();
    match ret {
        Ok(claims) => {
            return if let Some(res_user_info) = ResUserInfo::get_by_uid(&conn, claims.uid) {
                Data::ok(res_user_info).to_json()
            } else {
                BusinessError::NotFound.into()
            };
        }
        Err(e) => {
            return e.into();
        }
    }
}

#[post("/tokens")]
pub async fn create_token(
    form: web::Json<NewTokenForm>,
    data: web::Data<ShareData>,
) -> Res {
    #[derive(Debug, Serialize, Deserialize)]
    struct Token {
        pub token: String,
    }

    let login_info = form.into_inner();

    if login_info.phone.clone().len() == 0 {
        return BusinessError::ValidationError { msg: "手机号不能为空。".to_string() }.into();
    }

    let re = Regex::new(r"^[1]([3-9])[0-9]{9}$").expect("手机号正则错误");
    if !re.is_match(login_info.phone.clone().as_str()) {
        return BusinessError::ValidationError { msg: "手机号格式不正确".to_string() }.into();
    }

    let len = login_info.password.clone().len();
    if len == 0 {
        return BusinessError::ValidationError { msg: "密码不能为空。".to_string() }.into();
    } else if len < 6 || len > 100 {
        return BusinessError::ValidationError { msg: "密码长度必须大于 6 个字符".to_string() }.into();
    }

    let ret = login(&data.postgres(), login_info.phone, login_info.password);
    match ret {
        Ok(token) => {
            Data::ok(Token { token }).to_json()
        }
        Err(e) => {
            e.into()
        }
    }
}


#[get("/test")]
pub async fn test(
    req: HttpRequest,
    data: web::Data<ShareData>,
) -> Res {
    if let Err(e) = check_permission(&req, Role::Headmaster) {
        return e.into();
    }

    Data::ok(User::read(&data.postgres(), 1, 10)).to_json()
}
